package com.zhou.service;

import com.zhou.dao.OrderDao;
import com.zhou.dao.StockDao;
import com.zhou.dao.UserDao;
import com.zhou.entity.Order;
import com.zhou.entity.Stock;
import com.zhou.entity.User;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;

import java.util.Date;
import java.util.concurrent.TimeUnit;

@Service
//声明式事务管理
@Transactional
@Slf4j
public class OrderServiceImpl implements OrderService{

    @Autowired
    private StockDao stockDao;
    @Autowired
    private OrderDao orderDao;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private UserDao userDao;

    @Override
    public int kill(Integer id, Integer userid, String md5) {
        //redis校验抢购时间
        if (!stringRedisTemplate.hasKey("kill" + id)) {
            throw new RuntimeException("秒杀超时，活动已经结束了！！！");
        }
        //验证md5签名
        String hashKey = "KEY_" + userid + "_" + id;
        String s = stringRedisTemplate.opsForValue().get(hashKey);
        if (s == null) throw new RuntimeException("没有携带验证签名，请求不合法！");
        if (!s.equals(md5)) throw new RuntimeException("当前请求数据不合法，请稍后再试！");

        //根据商品id校验库存
        Stock stock = checkStock(id);
        updateSale(stock);
        return createOrder(stock);
    }

    @Override
    public String getMd5(Integer id, Integer userid) {
        //校验用户的合法性
        User user = userDao.findById(userid);
        if(user == null) throw new RuntimeException("用户信息不存在！！！");
        log.info("用户信息：[{}]",user.toString());

        //校验商品的合法性
        Stock stock = stockDao.checkStock(id);
        if (stock == null) throw new RuntimeException("商品信息不存在！！！");
        log.info("商品信息：[{}]", stock.toString());

        //生成hashKey
        String hashKey = "KEY_" + userid + "_" + id;
        String key = DigestUtils.md5DigestAsHex((userid + id + "iloveyou").getBytes());
        stringRedisTemplate.opsForValue().set(hashKey, key, 3600, TimeUnit.SECONDS);
        log.info("redis写入：[{}] [{}]",hashKey, key);
        return key;
    }

    //校验库存
    private Stock checkStock(Integer id){
        Stock stock = stockDao.checkStock(id);
        if(stock.getSale().equals(stock.getCount())){
            throw new RuntimeException("库存不足！！！");
        }
        return stock;
    }
    //扣除库存
    private void updateSale(Stock stock){
        //使用乐观锁，交给数据库层面去解决超卖的问题，因为数据库不能并发写；
        int updateRows = stockDao.updateSale(stock);
        if (updateRows == 0){
            throw new RuntimeException("抢购失败，请重试！");
        }
    }
    //创建订单
    private Integer createOrder(Stock stock){
        Order order = new Order();
        order.setSid((stock.getId())).setName(stock.getName()).setCreateTime(new Date());
        orderDao.createOrder(order);
        return order.getId();
    }
}
